﻿using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.IO;
using System.Windows.Data;
using System.Windows.Input;

namespace Reckoning
{
    /// <summary>
    /// Model for Stop Words view
    /// </summary>
    public class StopWordsViewModel : NotifyPropertyChangedBase, IStopWordsViewModel
    {
        #region Commands
        public ICommand SaveStopWordsCommand
        {
            get
            {
                return _saveStopWordsCommand;
            }
        }
        
        public ICommand RestoreStopWordsCommand
        {
            get
            {
                return _restoreStopWordsCommand;
            }
        }

        private readonly DelegateCommand<object> _saveStopWordsCommand;
        private readonly DelegateCommand<object> _restoreStopWordsCommand;
        #endregion

        #region Properties       
        private bool _changed;
        public bool Changed
        {
            get
            {
                return _changed;
            }
            private set
            {
                CheckPropertyChanged<bool>("Changed", ref _changed, ref value);                
                _saveStopWordsCommand.RaiseCanExecuteChanged();
                _restoreStopWordsCommand.RaiseCanExecuteChanged();                
            }
        }

        private HashSet<StopWordInfo> _stopWords;
        public HashSet<StopWordInfo> StopWords
        {
            get
            {
                return _stopWords;
            }

            private set
            {
                CheckPropertyChanged<HashSet<StopWordInfo>>("StopWords", ref _stopWords, ref value);                
            }
        }

        /// <summary>
        /// List of stop words for editing
        /// </summary>
        private ObservableCollectionWithChildNotify<StopWordInfo> _stopWordsEdit;
        public ObservableCollectionWithChildNotify<StopWordInfo> StopWordsEdit
        {
            get
            {                
                return _stopWordsEdit;
            }
            set
            {
                CheckPropertyChanged<ObservableCollectionWithChildNotify<StopWordInfo>>("StopWordsEdit", ref _stopWordsEdit, ref value);     
            }
        }

        IView _window;
        #endregion

        #region IStopWordsViewModel Methods
        public void Run()
        {
            _window.SetModel(this);
            _window.Show();
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Constructor
        /// </summary>
        public StopWordsViewModel(IView window)
        {
            _saveStopWordsCommand = new DelegateCommand<object>(SaveStopWords, CanExecute);
            _restoreStopWordsCommand = new DelegateCommand<object>(RestoreStopWords, CanExecute);
            
            _changed = false;

            _stopWordsEdit = new ObservableCollectionWithChildNotify<StopWordInfo>();
            ReadStopWordsSettings(true);
            if (StopWords != null)
            {
                _stopWordsEdit = new ObservableCollectionWithChildNotify<StopWordInfo>();
                List<StopWordInfo> list = new List<StopWordInfo>(StopWords);
                foreach (StopWordInfo swi in list)
                {
                    _stopWordsEdit.Add(swi);
                }
            }
            _stopWordsEdit.CollectionChanged += (o, e) => Changed = true;
            _stopWordsEdit.ChildElementPropertyChanged += (e) => Changed = true;

            _window = window;
        }
        
        /// <summary>
        /// Get the edited stop words and save them to the settings
        /// </summary>
        public void SaveStopWords(object param)
        {
            // populate the hashset
            HashSet<StopWordInfo> hash = new HashSet<StopWordInfo>();
            foreach (StopWordInfo swi in _stopWordsEdit)
                hash.Add(swi);

            StopWords = hash;

            WriteStopWordsSettings();
            Changed = false;
        }

        /// <summary>
        /// Whether button is enabled
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public bool CanExecute(object param)
        {
            return Changed;
        }

        /// <summary>
        /// Read the App settings for the list of stop words
        /// </summary>
        public void RestoreStopWords(object param)
        {
            ReadStopWordsSettings(false);            
            StopWordsEdit.Clear();
            List<StopWordInfo> list = new List<StopWordInfo>(StopWords);
            foreach (StopWordInfo swi in list)
            {
                StopWordsEdit.Add(swi);
            }
            Changed = false;
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Get the stop word list from the App or User settings
        /// </summary>
        /// <param name="user">true to get User settings</param>
        private void ReadStopWordsSettings(bool user)
        {
            StringCollection collection;
            if (user && Properties.Settings.Default.UserStopWords != null)
                collection = Properties.Settings.Default.UserStopWords;
            else
                collection = Properties.Settings.Default.AppStopWords;

            StopWords = new HashSet<StopWordInfo>();
            foreach (string s in collection)
                StopWords.Add(new StopWordInfo(s));
        }

        /// <summary>
        /// Set the stop word list in the User settings
        /// </summary>        
        private void WriteStopWordsSettings()
        {
            StringCollection collection = new StringCollection();
            foreach (StopWordInfo swi in StopWords)
                collection.Add(swi.Word);

            Properties.Settings.Default.UserStopWords = collection;
        }
        #endregion
    }
}
